package com.codingfly;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.GlobalConfig;
import com.baomidou.mybatisplus.generator.config.ITypeConvert;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.TemplateType;
import com.baomidou.mybatisplus.generator.config.builder.Entity;
import com.baomidou.mybatisplus.generator.config.builder.Mapper;
import com.baomidou.mybatisplus.generator.config.builder.Service;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.util.Collections;

/**
 * com.baomidou:mybatis-plus-generator:3.5.6版本官方越写越烂，越搞越复杂，写成屎，还不如老版本。
 * 新版 com.baomidou:mybatis-plus-generator:3.5.6 有无数坑人配置，感觉官方越写越烂了，还不如老版本。
 * 新版具体垃圾地方，非人类设计
 * 01）globalConfig不设置outputDir，会在D盘生成，直接抛错让开发看到异常，然后设置输出路径不行吗，竟然私自设置输出路径
 * 02）packageConfig不设置parent，私自使用 com.baomidou 作为包名前缀，其他所有项目几乎不会有谁用 com.baomidou 做包名，垃圾默认配置
 * 03）strategyConfig方法的 builder.controllerBuilder().disable(); 是垃圾代码，配置不生成controller，结果生成了controller
 * 04）com.baomidou:mybatis-plus-generator:3.5.6 版本 .templateConfig(builder -> { builder.disable(TemplateType.CONTROLLER); }) 和 builder.controllerBuilder().disable();  同时配置才生效
 */
public class CodeGenerator {

    public static void main(String[] args) {
        String rootProjectPath = System.getProperty("user.dir");

        FastAutoGenerator.create("jdbc:mysql://localhost:3306/baseweb", "root", "123456")
                .dataSourceConfig(builder -> {
                    builder.typeConvert(new MySqlTypeConvertCustom());
                })
                // 全局配置 可以配置的具体查看 GlobalConfig.Builder
                .globalConfig(builder -> {
                    builder.author("author") // 设置作者
                            .disableOpenDir() // 禁止打开输出目录
                            .dateType(DateType.ONLY_DATE)
                            //.enableSwagger() // 开启 swagger 模式，默认不开启
                            .outputDir(rootProjectPath + "/src/main/java"); // 指定输出目录
                })
                // 包配置
                .packageConfig((builder) -> builder.parent("") // 不配置，默认生成 com.baomidou 包名，坑爹的官方，越写越烂
                        .mapper("com.codingfly.mapper")
                        .entity("com.codingfly.mapper.entity")
                        .service("com.codingfly.service")
                        .serviceImpl("com.codingfly.service.impl")
                        .pathInfo(Collections.singletonMap(OutputFile.xml, rootProjectPath+"/src/main/resources/mapper")) // 将Mapper xml生成到resources目录下
                )
                // 策略配置
                // 可以配置的项具体可看 StrategyConfig.Builder
                .strategyConfig(builder -> {
                    builder.addInclude("t_article")
                            .addFieldPrefix("F_")
                            .addTablePrefix("t_");

                    Mapper.Builder mapperBuilder = builder.mapperBuilder();
                    mapperBuilder.enableMapperAnnotation() // 开启 @Mapper 注解
                            .superClass(BaseMapper.class)  // 设置父类
                            .formatMapperFileName("%sMapper") // 设置 mapper 文件名称
                            .formatXmlFileName("%sMapper")    // 设置 xml 实现类文件名称
                            .enableBaseColumnList()
                            .enableBaseResultMap();    // 生成通用的resultMap

                    Entity.Builder entityBuilder = builder.entityBuilder();
                    entityBuilder.formatFileName("%sEntity")
                            .enableTableFieldAnnotation()
                            .enableLombok()
                            .naming(NamingStrategy.underline_to_camel)
                            .columnNaming(NamingStrategy.underline_to_camel);

                    Service.Builder serviceBuilder = builder.serviceBuilder();
                    serviceBuilder.formatServiceFileName("%sService")          // 设置 service 接口文件名称
                                  .formatServiceImplFileName("%sServiceImpl"); // 设置 service 实现类文件名称

                    builder.controllerBuilder().disable(); // 无效配置，github上面很多人都反馈了这个问题
                    // builder.controllerBuilder().disable(); 和 builder.disable(TemplateType.CONTROLLER); 同时配置，才生效不生成controller

                })
                // 模板引擎
                .templateEngine(new FreemarkerTemplateEngine())
                .templateConfig(builder -> {
                    builder.disable(TemplateType.CONTROLLER); // builder.controllerBuilder().disable(); 和 builder.disable(TemplateType.CONTROLLER); 同时配置，才生效不生成controller
                })
                // 执行方法
                .execute();

    }

    /**
     * 将 tinyint 类型，生成Integer类型的Java属性
     */
    public static class MySqlTypeConvertCustom extends MySqlTypeConvert implements ITypeConvert {
        @Override
        public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
            String t = fieldType.toLowerCase();
            if (t.contains("tinyint")) {
                return DbColumnType.INTEGER;
            }
            return super.processTypeConvert(globalConfig, fieldType);
        }
    }

}
